#ifndef __SCHEDULER_H__
#define __SCHEDULER_H__

#include "PCB.hpp"
#include <deque>
#include <map>
#include <memory>

class Scheduler
{
public:
    /*
        create
        创建新进程，加入new
        @param ppid: int 父进程pid
        @param commands: const vector<Command>& 指令表
        @param priority: 优先级参数

        @return pid: 新进程的pid，-1表示错误
     */
    virtual int create(int ppid, const std::vector<Command> &commands, int pc, PCB::Priority priority) = 0;

    /*
        admit
        将某个进程从new变为ready
        @param pid: int
        @return int: 0成功 -1失败
     */
    virtual int admit(int pid) = 0;

    /*
        get_task
        获取一个将要执行的ready进程号
        @return int pid -1表示无进程
     */
    virtual int get_task() = 0;

    /*
        set_run
        将进程标记为run
        @param pid
     */
    virtual int set_run(int pid) = 0;

    /*
        set_ready
        @param: pid
     */
    virtual int set_ready(int pid) = 0;

    /*
        set_wait
        @param: pid
     */
    virtual int set_wait(int pid) = 0;

    /*
        exit
        @param: pid
     */
    virtual int exit(int pid) = 0;

    /*
        kill
        @param: pid
     */
    virtual int kill(int pid) = 0;

    /*
        get_PCB
        @param: pid
        @return shared_ptr<PCB>
     */
    virtual std::shared_ptr<PCB> get_PCB(int pid) = 0;
};

class FCFSScheduler : public Scheduler
{
public:
    virtual int create(int ppid, const std::vector<Command> &commands, int pc, PCB::Priority priority);
    virtual int admit(int pid);
    virtual int get_task();
    virtual int set_run(int pid);
    virtual int set_ready(int pid);
    virtual int set_wait(int pid);
    virtual int exit(int pid);
    virtual int kill(int pid);
    virtual std::shared_ptr<PCB> get_PCB(int pid);

    FCFSScheduler(int max_progress_count = 0) : max_progress_count(max_progress_count){};

private:
    std::deque<int> new_queue;
    std::deque<int> ready_queue;
    std::deque<int> run_queue;
    std::deque<int> wait_queue;
    std::map<int, std::shared_ptr<PCB>> PCB_table;

    int max_progress_count = 0;
};

class HRRNScheduler : public Scheduler
{
public:
    virtual int create(int ppid, const std::vector<Command> &commands, int pc, PCB::Priority priority);
    virtual int admit(int pid);
    virtual int get_task();
    virtual int set_run(int pid);
    virtual int set_ready(int pid);
    virtual int set_wait(int pid);
    virtual int exit(int pid);
    virtual int kill(int pid);
    virtual std::shared_ptr<PCB> get_PCB(int pid);

    HRRNScheduler(int max_progress_count = 0) : max_progress_count(max_progress_count){};

private:
    std::deque<int> new_queue;
    std::deque<int> ready_queue;
    std::deque<int> run_queue;
    std::deque<int> wait_queue;
    std::map<int, std::shared_ptr<PCB>> PCB_table;

    int max_progress_count = 0;
};

#endif
